home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / cpp / exception.c < prev    next >
C/C++ Source or Header  |  1992-04-13  |  9KB  |  300 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *
  16.  * Created: MJF 07/05/89 -- Initial design and implementation.
  17.  * Changed: MJF 02/20/90 -- Added group name support.
  18.  * Changed: MJF 03/01/91 -- Added throw code written by grahamd@otc.otca.oz.au
  19.  *
  20.  * The C++ exception handling defmacro
  21.  *
  22.  * To use, declare:
  23.  *     #pragma defmacro EXCEPTION "exception" exception_g format_msg err_msg
  24.  *                                hprintf delimiter=)
  25.  *
  26.  * where: exception_g is the name of the global variable to use as a temporary,
  27.  *        format_msg is the name of the slot in the exception class, err_msg
  28.  *        is the name of the text package for error message strings, and 
  29.  *        hprintf is  the name of the function which returns a formatted string
  30.  *        from the heap.
  31. */
  32.  
  33. /*
  34.  * EXCEPTION is a cpp macro used to construct an Exception object.
  35.  * EXCEPTION has the following argument options:
  36.  *
  37.  * EXCEPTION(excp_name [, group_names] [, format_string] [rest_args])
  38.  *
  39.  * where   group_names := group_name [, group_names ]
  40.  *           rest_args := rest_arg | [, rest_arg]
  41.  *            rest_arg := format_arg | key_value_slot_arg
  42.  *          format_arg := name
  43.  *  key_value_slot_arg := name = value
  44.  *       format_string := "string"
  45.  *          group_name := SYM(name)
  46.  *          excp_name  := name
  47.  *
  48.  * In general:
  49.  *
  50.  * EXCEPTION(excp_name, SYM(group_name1), SYM(group_name2), format_string, 
  51.  *           key1=val1, arg1, key2=val2, arg2);
  52.  *
  53.  * would generate:
  54.  *
  55.  * (Exception_g = new excp_name(2, SYM(group_name1), SYM(group_name2)), 
  56.  *  Exception_g->format_msg = hprintf(ERR_MSG(format_string), 
  57.  *                                    val1, arg1, val2, arg2),
  58.  *  Exception_g->key1 = val1, 
  59.  *  Exception_g->key2 = val2, 
  60.  *  Exception_g);
  61.  *
  62.  * Note that the value of the key-val-slot-args and the non-key-val-slot-args
  63.  * are all gathered as format args for the hprintf function.  Also note that
  64.  * the key-val-slot-args and the non-key-args are intermixed.  It mainly
  65.  * depends on the format_string requirements.
  66.  *
  67.  * More specific examples using EXCEPTION:
  68.  *
  69.  * (1) EXCEPTION with group_name, error type and format string.
  70.  *
  71.  * EXCEPTION(Error, Serios_Error, "Serious problem here.");
  72.  *
  73.  * would generate:
  74.  *
  75.  *  (Exception_g = new Error(SYM(Serious_Error)), 
  76.  *   Exception_g->format_msg = hprintf(ERR_MSG("Serious problem here.")),
  77.  *   Exception_g);
  78.  *  
  79.  *
  80.  * (2) EXCEPTION with error type, format string and mixture of slot arguments
  81.  *    and format arguments.
  82.  * 
  83.  * Assume a defined error type, Bad_Argment_Error, with two slots, arg_name and 
  84.  * arg_value.
  85.  *
  86.  * Class Bad_Argument_Error : public Fatal {
  87.  * public:
  88.  *  char* arg_name;
  89.  *  int arg_value;
  90.  *  Bad_Argment_Error();
  91.  * }
  92.  *
  93.  * then...
  94.  *
  95.  * EXCEPTION(Bad_Argument_Error, 
  96.  *           "Arg %s has value %d which is out of range for %s."
  97.  *           arg_name="foo", arg_value=x, vec1);
  98.  *
  99.  * would generate...
  100.  *
  101.  *  (Exception_g = new Bad_Argument_Error(),
  102.  *   Exception_g->arg_name = "foo",
  103.  *   Exception_g->arg_value = x,
  104.  *   Exception_g->format_msg =
  105.  *     hprintf(ERR_MSG("Arg %s has value %d which is out of range for %s."),
  106.  *             "foo", x, vec1),
  107.  *   Exception_g);
  108.  *
  109.  * (3) EXCEPTION with error type, and slot arguments (but no format message).
  110.  *
  111.  * Assume a defined error type, Out_Of_Range, with two slots, value and vector.
  112.  * 
  113.  * Class Out_of_Range : public Fatal {
  114.  * public:
  115.  *  int value;
  116.  *  Generic vector;
  117.  *  Out_of_Range() {
  118.  *    format_msg = "Value of %d is out of range for Vector %s."
  119.  *  }
  120.  *  void report(ostream& os) {
  121.  *    os << this->message_prefix();
  122.  *    os << form(format_msg, value, vector);
  123.  *  }
  124.  * };
  125.  *  then...
  126.  *
  127.  *  EXCEPTION(Out_of_Range, value=n, vector=v1);
  128.  *
  129.  *  would generate...
  130.  *
  131.  *  (Exception_g = new Out_of_Range(),
  132.  *   Exception_g->value =  n,
  133.  *   Exception_g->vector = v1,
  134.  *   Exception_g);
  135.  *
  136. */
  137.  
  138. #include "defmacio.h"
  139. #include "macro.h"
  140.  
  141. #define MAXBUF   512
  142. #define MAXGROUP 32
  143.  
  144. exception(argc, argv)
  145.  int argc;
  146.  char* argv[];
  147. {
  148.   char* global_excp;    /* Exception_g */
  149.   char* format_msg;    /* exception format message slot name */
  150.   char* group_fcn;    /* function which updates the group slot */
  151.   char* err_pkg;        /* text package name for error message strings */
  152.   char* format_fcn;    /* hprintf (heap print) function */
  153.   
  154.   char buffer[MAXBUF];
  155.  
  156.   char* macname;    /* EXCEPTION is the macro name */
  157.   char* excp_name;      /* the name of the exception type */
  158.   char* group_names[MAXGROUP];
  159.   int group_count;
  160.   Arg* argp = NULL;    /* always points to first arg in macro */
  161.   Arg* excp_args;    /* EXCEPTION macro arg pointer */
  162.   Arg* fs_args;        /* pointer to format or slot arguments*/
  163.  
  164.   if(argc <= 3) {
  165.     fprintf(stderr, "Not enough arguments to #pragma defmacro exception\n");
  166.     return(1);
  167.   }
  168.   global_excp = argv[1];
  169.   format_msg = argv[2];
  170.   group_fcn = argv[3];
  171.   err_pkg = argv[4];
  172.   format_fcn = argv[5];
  173.  
  174.   copytoken(buffer);        /* Grab the macro name */
  175.   macname = savestring(buffer);
  176.  
  177.   /* Gather all EXCEPTION arguments */
  178.   if((argp = macro_args(macname)) == &arg_error) {  
  179.     fprintf(stderr, ".\n");
  180.     return(1);
  181.   }
  182.  
  183.   /* EXCEPTION takes at least one argument */
  184.   if((excp_args = argp) == NULL) {
  185.     fprintf(stderr, "EXCEPTION: No arguments specified.");
  186.     return(1);
  187.   }
  188.  
  189.   /* first EXCEPTION argument should be name of exception type */
  190.   excp_name = excp_args->name;
  191.   /* call exception constructor */
  192.   sprintf(buffer, "\n(%s = new %s()", global_excp, excp_name);
  193.   puts(buffer);
  194.  
  195.   group_count = 0;
  196.   /* the next EXCEPTION argument might be the optional group names */
  197.   for(excp_args = excp_args->next;
  198.       excp_args !=NULL && excp_args->name[0] != '"' 
  199.       && *excp_args->value == EOS && excp_args->value != NULL;
  200.       excp_args = excp_args->next, group_count++) {
  201.     group_names[group_count] = excp_args->name;
  202.   }
  203.  
  204.   if (group_count == 1) {
  205.     /* only one group name */
  206.     /* output: global_excp->group_fcn(group_name) */
  207.     sprintf(buffer, ",\n%s->%s(%s)", global_excp, group_fcn,
  208.                                      group_names[--group_count]);
  209.     puts(buffer);
  210.   }
  211.  
  212.   if (group_count != 0) {
  213.     /* more than one group name */
  214.     /* output: global_excp->group_fcn(group_count, group_name[0], ...,
  215.                                       ..., group_name[n-1])              */
  216.     sprintf(buffer, ",\n%s->%s(%d", 
  217.                     global_excp, group_fcn, group_count);
  218.     puts(buffer);
  219.     /* output all of the group names */
  220.     while (group_count != 0) {
  221.       sprintf(buffer, ", %s", group_names[--group_count]);
  222.       puts(buffer);
  223.     }
  224.     puts(")");   /* closing paren on group_fcn */
  225.   }
  226.  
  227.   /* the next EXCEPTION argument might be the optional format string */
  228.   if ((excp_args  != NULL) && (excp_args->name[0] == '"')) {
  229.     puts(",\n");
  230.     /* output: global_excp->format_msg = hprintf(err_msg(format_string) ...   */
  231.     sprintf(buffer, "%s->%s = %s(%s(%s)", global_excp, format_msg, format_fcn,
  232.                                       err_pkg, excp_args->name);
  233.     puts(buffer);
  234.     /* output: format_arg1, format_arg2, ...)  */
  235.     excp_args = excp_args->next;   /* skip format string */
  236.     for(fs_args=excp_args;       /* now output each format arg */
  237.         fs_args != NULL;
  238.         fs_args=fs_args->next) {
  239.       puts(", ");
  240.       if (*fs_args->value != EOS)  /* check key=value arg */
  241.     puts(fs_args->value);
  242.       else puts(fs_args->name);
  243.     }
  244.     putchar(')');   /* closing paren for format function, hprintf */
  245.   }
  246.  
  247.   /* the next EXCEPTION argument might be key-value slots */
  248.   for(fs_args = excp_args; fs_args != NULL; fs_args=fs_args->next) {
  249.     if (*fs_args->value != EOS) {
  250.       /* output: global_excp->key = value, */
  251.       puts(",\n");
  252.       sprintf(buffer, "((%s*) %s)->%s = %s", excp_name, global_excp, 
  253.                                          fs_args->name, fs_args->value);
  254.       puts(buffer);
  255.     }
  256.   }
  257.   
  258.   
  259.   /* last output is the global exception name */
  260.   sprintf(buffer, ",\n(%s*) %s)", excp_name, global_excp);
  261.   puts(buffer);
  262.  
  263.   for(argp = argp; argp != NULL;) {
  264.     Arg* old = argp;
  265.     argp = argp->next;
  266.     free(old->name);
  267.     if (*old->value) free(old->value);
  268.     free(old);
  269.   }
  270.   free(macname);
  271.   return 0;
  272. }
  273.  
  274. /*
  275.  * Handle throw translation
  276.  *
  277.  * throw Exception(__LINE__,__FILE__,"error");
  278.  *
  279.  * expands to
  280.  *
  281.  *  (new Exception(__LINE__,__FILE__,"error"), terminate());
  282.  *
  283.  */
  284.  
  285. int throw (argc, argv)
  286.   int argc;
  287.   char** argv;
  288. {
  289.   char buff[256];
  290.   char* line;
  291.   if (copytoken(buff) == NULL)
  292.     return 1;
  293.   puts("( new ");
  294.   line = scan_token(";");
  295.   puts(line);
  296.   puts(", terminate() );");
  297.   return 0;
  298. }
  299.  
  300.